using System;
using System.Windows;
using System.Windows.Threading;

namespace CommonCore.Extensions
{
    public static class Threading
    {
        /// <summary>
        /// Returns the UI Thread Dispather
        /// </summary>
        public static Dispatcher Dispatcher
        {
            get
            {
#if SILVERLIGHT
                return Deployment.Current.Dispatcher;
#else
                return Application.Current.Dispatcher;
#endif
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <param name="action">The action to perform</param>
        public static void InvokeOnUIThread(this Action action)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action();
            } else
            {
                Dispatcher.BeginInvoke(action);
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <typeparam name="TArg1">The type of the first argument</typeparam>
        /// <param name="action">The action to perform</param>
        /// <param name="arg1">The first argument of the action</param>
        public static void InvokeOnUIThread<TArg1>(this Action<TArg1> action, TArg1 arg1)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action(arg1);
            } else
            {
                Dispatcher.BeginInvoke(action, arg1);
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <typeparam name="TArg1">The type of the first argument</typeparam>
        /// <typeparam name="TArg2">The type of the second argument</typeparam>
        /// <param name="action">The action to perform</param>
        /// <param name="arg1">The first argument of the action</param>
        /// <param name="arg2">The second argument of the action</param>
        public static void InvokeOnUIThread<TArg1, TArg2>(this Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action(arg1, arg2);
            } else
            {
                Dispatcher.BeginInvoke(action, arg1, arg2);
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <typeparam name="TArg1">The type of the first argument</typeparam>
        /// <typeparam name="TArg2">The type of the second argument</typeparam>
        /// <typeparam name="TArg3">The type of the third argument</typeparam>
        /// <param name="action">The action to perform</param>
        /// <param name="arg1">The first argument of the action</param>
        /// <param name="arg2">The second argument of the action</param>
        /// <param name="arg3">The third argument of the action</param>
        public static void InvokeOnUIThread<TArg1, TArg2, TArg3>(this Action<TArg1, TArg2, TArg3> action, TArg1 arg1, TArg2 arg2, TArg3 arg3)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action(arg1, arg2, arg3);
            } else
            {
                Dispatcher.BeginInvoke(action, arg1, arg2, arg3);
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <typeparam name="TArg1">The type of the first argument</typeparam>
        /// <typeparam name="TArg2">The type of the second argument</typeparam>
        /// <typeparam name="TArg3">The type of the third argument</typeparam>
        /// <typeparam name="TArg4">The type of the fourth argument</typeparam>
        /// <param name="action">The action to perform</param>
        /// <param name="arg1">The first argument of the action</param>
        /// <param name="arg2">The second argument of the action</param>
        /// <param name="arg3">The third argument of the action</param>
        /// <param name="arg4">The fourth argument of the action</param>
        public static void InvokeOnUIThread<TArg1, TArg2, TArg3, TArg4>(this Action<TArg1, TArg2, TArg3, TArg4> action, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action(arg1, arg2, arg3, arg4);
            } else
            {
                Dispatcher.BeginInvoke(action, arg1, arg2, arg3, arg4);
            }
        }

        /// <summary>
        /// Invokes the specified action on the UI Thread
        /// </summary>
        /// <typeparam name="TArg1">The type of the first argument</typeparam>
        /// <typeparam name="TArg2">The type of the second argument</typeparam>
        /// <typeparam name="TArg3">The type of the third argument</typeparam>
        /// <typeparam name="TArg4">The type of the fourth argument</typeparam>
        /// <typeparam name="TArg5">The type of the fifth argument</typeparam>
        /// <param name="action">The action to perform</param>
        /// <param name="arg1">The first argument of the action</param>
        /// <param name="arg2">The second argument of the action</param>
        /// <param name="arg3">The third argument of the action</param>
        /// <param name="arg4">The fourth argument of the action</param>
        /// <param name="arg
        /// 5">The fifth argument of the action</param>
        public static void InvokeOnUIThread<TArg1, TArg2, TArg3, TArg4, TArg5>(this Action<TArg1, TArg2, TArg3, TArg4, TArg5> action, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
        {
            if (action == null) throw new ArgumentNullException("action");
            if (Dispatcher.CheckAccess())
            {
                action(arg1, arg2, arg3, arg4, arg5);
            } else
            {
                Dispatcher.BeginInvoke(action, arg1, arg2, arg3, arg4, arg5);
            }
        }
    }
}